﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using AstLowerer.Capabilities;
using VulcanEngine.Common;
using VulcanEngine.IR;
using VulcanEngine.IR.Ast;
using VulcanEngine.IR.Ast.Table;
using VulcanEngine.Phases;

namespace AstLowerer
{
    [PhaseFriendlyName("AstLowererPhase")]
    public class AstLowererPhase : IPhase
    {
        private readonly string _workflowUniqueName;

        public string Name
        {
            get { return "AstLowererPhase"; }
        }

        public string WorkflowUniqueName
        {
            get { return _workflowUniqueName; }
        }

        public Type InputIRType
        {
            get { return typeof(AstIR); }
        }

        public AstLowererPhase(string workflowUniqueName)
        {
            _workflowUniqueName = workflowUniqueName;
        }

        public IIR Execute(Collection<IIR> predecessorIRs)
        {
            return Execute(IRUtility.MergeIRList(Name, predecessorIRs));
        }

        public IIR Execute(IIR predecessorIR)
        {
            var ir = (AstIR)predecessorIR;
            CloneTableLowerer.ProcessCloneTable(ir.AstRootNode.SymbolTable);
            PrincipalsLowerer.ProcessPrincipals(ir.AstRootNode);
            SchemaLowerer.ProcessSchemas(ir.AstRootNode);

            ProcessTables(ir.AstRootNode);

            RetryContainerLowerer.ProcessRetryContainers(ir.AstRootNode.SymbolTable);

            EtlFragmentsLowerer.ProcessEtlFragments(ir.AstRootNode.SymbolTable);
            LateArrivingLowerer.ProcessLateArrivingLookupTransformations(ir.AstRootNode.SymbolTable);
            IsNullPatcherLowerer.ProcessIsNullPatcherTransformations(ir.AstRootNode.SymbolTable);
            SlowlyChangingDimensionsLowerer.ProcessSlowlyChangingDimensionTransformations(ir.AstRootNode.SymbolTable);
            StagingContainerLowerer.ProcessContainers(ir.AstRootNode.SymbolTable);
            StoredProcedureLowerer.ProcessStoredProcedures(ir.AstRootNode.SymbolTable);
            MergeLowerer.ProcessMerges(ir.AstRootNode.SymbolTable);
            ExecutePackageLowerer.ProcessExecutePackageTransformations(ir.AstRootNode.SymbolTable);

            return ir;
        }

        private static void ProcessTables(AstRootNode astRootNode)
        {
            var tables = new List<AstTableBaseNode>(astRootNode.Tables);
            foreach (var dimension in astRootNode.Dimensions)
            {
                tables.Add(dimension);
            }

            foreach (var fact in astRootNode.Facts)
            {
                tables.Add(fact);
            }

            foreach (AstTableNode table in tables)
            {
                if (table.LateArriving)
                {
                    LateArrivingLowerer.ProcessLateArrivingTable(table);
                }

                if (table.HasScdColumns)
                {
                    SlowlyChangingDimensionsLowerer.ProcessTableScdColumns(table);
                }

                foreach (var staticSourcePackage in StaticSourcesLowerer.ProcessTableStaticSource(table))
                {
                    astRootNode.Packages.Add(staticSourcePackage);
                }

                if (!(table is AstTableCloneNode) && table.EmitVersionNumber)
                {
                    var versionNumber = new AstTableColumnNode(table) 
                    { 
                        Name = "VersionNumber",
                        ColumnType = ColumnType.Binary,
                        Length = 8,
                        CustomType="rowversion",
                        IsAssignable=false,
                        IsNullable = false,
                        IsAutoGenerated = true 
                    };
                    table.Columns.Add(versionNumber);
                }

                if (table.Emit)
                {
                    astRootNode.Packages.Add(TableLowerer.ProcessTable(table));
                }
            }
        }
    }
}
